home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / tiff / tools / sgigt.c < prev    next >
C/C++ Source or Header  |  1992-03-30  |  35KB  |  1,577 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/tools/RCS/sgigt.c,v 1.33 92/03/31 09:20:41 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler
  7.  * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
  8.  *
  9.  * Permission to use, copy, modify, distribute, and sell this software and 
  10.  * its documentation for any purpose is hereby granted without fee, provided
  11.  * that (i) the above copyright notices and this permission notice appear in
  12.  * all copies of the software and related documentation, and (ii) the names of
  13.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  14.  * publicity relating to the software without the specific, prior written
  15.  * permission of Sam Leffler and Silicon Graphics.
  16.  * 
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  18.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  19.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  20.  * 
  21.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  22.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  23.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  25.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  26.  * OF THIS SOFTWARE.
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <gl.h>
  31. #include <device.h>
  32. #include "tiffio.h"
  33.  
  34. typedef    unsigned char u_char;
  35. typedef    unsigned short u_short;
  36. typedef    unsigned int u_int;
  37. typedef    unsigned long u_long;
  38.  
  39. /* XXX fudge adjustment for window borders */
  40. #define    YFUDGE    20
  41. #define    XFUDGE    20
  42.  
  43. Cursor    hourglass = {
  44.     0x1ff0, 0x1ff0, 0x0820, 0x0820,
  45.     0x0820, 0x0c60, 0x06c0, 0x0100,
  46.     0x0100, 0x06c0, 0x0c60, 0x0820,
  47.     0x0820, 0x0820, 0x1ff0, 0x1ff0
  48. };
  49. u_long    *raster;            /* displayable image */
  50. u_long    width, height;            /* image width & height */
  51. u_short    bitspersample;
  52. u_short    samplesperpixel;
  53. u_short    photometric;
  54. u_short    orientation;
  55. u_short    *redcmap, *greencmap, *bluecmap;/* colormap for pallete images */
  56. u_short    YCbCrHorizSampling, YCbCrVertSampling;
  57. float    *YCbCrCoeffs;
  58. float    *refBlackWhite;
  59. int    isRGB = -1;
  60. int    verbose = 0;
  61. int    stoponerr = 0;            /* stop on read error */
  62.  
  63. char    *filename;
  64.  
  65. static    void checkImage();
  66. static    gt();
  67.  
  68. static void
  69. usage()
  70. {
  71.     fprintf(stderr, "usage: tiffgt [-d dirnum] [-f] [-lm] [-s] filename\n");
  72.     exit(-1);
  73. }
  74.  
  75. main(argc, argv)
  76.     int argc;
  77.     char *argv[];
  78. {
  79.     char title[1024];
  80.     char *cp, *rindex();
  81.     long max;
  82.     TIFF *tif;
  83.     int fg = 0, c, dirnum = -1, order = 0;
  84.     extern int optind;
  85.     extern char *optarg;
  86.  
  87.     while ((c = getopt(argc, argv, "d:cerflmsv")) != -1)
  88.         switch (c) {
  89.         case 'c':
  90.             isRGB = 0;
  91.             break;
  92.         case 'd':
  93.             dirnum = atoi(optarg);
  94.             break;
  95.         case 'f':
  96.             fg = 1;
  97.             break;
  98.         case 'l':
  99.             order = FILLORDER_LSB2MSB;
  100.             break;
  101.         case 'm':
  102.             order = FILLORDER_MSB2LSB;
  103.             break;
  104.         case 'r':
  105.             isRGB = 1;
  106.             break;
  107.         case 's':
  108.             stoponerr = 1;
  109.             break;
  110.         case 'v':
  111.             verbose = 1;
  112.             break;
  113.         case '?':
  114.             usage();
  115.             /*NOTREACHED*/
  116.         }
  117.     if (argc - optind < 1)
  118.         usage();
  119.     filename = argv[optind];
  120.     tif = TIFFOpen(filename, "r");
  121.     if (tif == NULL)
  122.         exit(-1);
  123.     if (dirnum != -1 && !TIFFSetDirectory(tif, dirnum)) {
  124.         TIFFError(filename, "Error, seeking to directory %d", dirnum);
  125.         exit(-1);
  126.     }
  127.     checkImage(tif);
  128.     if (order)
  129.         TIFFSetField(tif, TIFFTAG_FILLORDER, order);
  130.     /*
  131.      * Use a full-color window if the image is
  132.      * full color or a palette image and the
  133.      * hardware support is present.
  134.      */
  135.     if (isRGB == -1)
  136.         isRGB = (bitspersample >= 8 &&
  137.             (photometric == PHOTOMETRIC_RGB ||
  138.              photometric == PHOTOMETRIC_YCBCR ||
  139.              photometric == PHOTOMETRIC_PALETTE));
  140.     /*
  141.      * Check to see if the hardware can display 24-bit RGB.
  142.      */
  143.     if (isRGB && getgdesc(GD_BITS_NORM_SNG_RED) < bitspersample &&
  144.       !getgdesc(GD_DITHER))
  145.         isRGB = 0;
  146.     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
  147.     max = getgdesc(GD_XPMAX) - XFUDGE;
  148.     if (width > max)
  149.         width = max;
  150.     TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
  151.     max = getgdesc(GD_YPMAX) - YFUDGE;
  152.     if (height > max)
  153.         height = max;
  154.     prefsize(width, height);
  155.     cp = rindex(filename, '/');
  156.     if (cp == NULL)
  157.         cp = filename;
  158.     else
  159.         cp++;
  160.     if (fg)
  161.         foreground();
  162.     strcpy(title, cp);
  163.     if (dirnum > 0 || verbose) {
  164.         char buf[40];
  165.         sprintf(buf, " [%d]", dirnum == -1 ? 0 : dirnum);
  166.         strcat(title, buf);
  167.     }
  168.     if (verbose)
  169.         strcat(title, isRGB ? " rgb" : " cmap");
  170.     if (winopen(title) < 0) {
  171.         TIFFError(filename, "Can not create window");
  172.         exit(-1);
  173.     }
  174.     raster = (u_long *)malloc(width * height * sizeof (long));
  175.     if (raster == 0) {
  176.         TIFFError(filename, "No space for raster buffer");
  177.         exit(-1);
  178.     }
  179.     singlebuffer();
  180.     if (isRGB) {
  181.         RGBmode();
  182.         gconfig();
  183.     } else {
  184.         cmode();
  185.         gconfig();
  186.     }
  187.     curstype(C16X1);
  188.     defcursor(1, hourglass);
  189.     setcursor(1, 0, 0);
  190.     rgb(0.5,0.5,0.5);
  191.     clear();
  192.     if (!gt(tif, width, height, raster))
  193.         exit(-1);
  194.     setcursor(0, 0, 0);
  195.     TIFFClose(tif);
  196.     qdevice(LEFTMOUSE);
  197.     for (;;) {
  198.         short val;
  199.         switch (qread(&val)) {
  200.         case REDRAW:
  201.             lrectwrite(0, 0, width-1, height-1, raster);
  202.             break;
  203.         case LEFTMOUSE:
  204.             if (val)
  205.                 exit(0);
  206.             break;
  207.         }
  208.     }
  209.     /*NOTREACHED*/
  210. }
  211.  
  212. static void
  213. checkImage(tif)
  214.     TIFF *tif;
  215. {
  216.     TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
  217.     switch (bitspersample) {
  218.     case 1: case 2: case 4:
  219.     case 8: case 16:
  220.         break;
  221.     default:
  222.         TIFFError(filename, "Sorry, can not handle %d-bit pictures",
  223.             bitspersample);
  224.         exit(-1);
  225.     }
  226.     TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
  227.     switch (samplesperpixel) {
  228.     case 1: case 3: case 4:
  229.         break;
  230.     default:
  231.             TIFFError(filename, "Sorry, can not handle %d-channel images",
  232.             samplesperpixel);
  233.         exit(-1);
  234.     }
  235.     if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) {
  236.         switch (samplesperpixel) {
  237.         case 1:
  238.             photometric = PHOTOMETRIC_MINISBLACK;
  239.             break;
  240.         case 3: case 4:
  241.             photometric = PHOTOMETRIC_RGB;
  242.             break;
  243.         default:
  244.             TIFFError(filename, "Missing needed \"%s\" tag",
  245.                 "PhotometricInterpretation");
  246.             exit(-1);
  247.         }
  248.         TIFFError(filename,
  249.             "No \"PhotometricInterpretation\" tag, assuming %s\n",
  250.             photometric == PHOTOMETRIC_RGB ? "RGB" : "min-is-black");
  251.     }
  252.     switch (photometric) {
  253.     case PHOTOMETRIC_MINISWHITE:
  254.     case PHOTOMETRIC_MINISBLACK:
  255.     case PHOTOMETRIC_RGB:
  256.     case PHOTOMETRIC_PALETTE:
  257.     case PHOTOMETRIC_YCBCR:
  258.         break;
  259.     default:
  260.         TIFFError(filename, "Sorry, can not handle image with %s=%d",
  261.             "PhotometricInterpretation", photometric);
  262.         exit(-1);
  263.     }
  264. }
  265.  
  266. static int
  267. checkcmap(n, r, g, b)
  268.     int n;
  269.     u_short *r, *g, *b;
  270. {
  271.     while (n-- > 0)
  272.         if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
  273.             return (16);
  274.     TIFFWarning(filename, "Assuming 8-bit colormap");
  275.     return (8);
  276. }
  277.  
  278. /*
  279.  * {red,green,blue}_inverse are tables in libgutil.a that
  280.  * do an inverse map from (r,g,b) to the closest colormap
  281.  * index in the "standard" GL colormap.  grey_inverse is
  282.  * the equivalent map for mapping greyscale values to
  283.  * colormap indices.  We access these maps directly instead
  284.  * of through the rgbi and greyi functions to avoid the
  285.  * additional overhead of the color calls that they make.
  286.  */
  287. extern    u_char red_inverse[256];
  288. extern    u_char green_inverse[256];
  289. extern    u_char blue_inverse[256];
  290. extern    u_char grey_inverse[256];
  291. #define    greyi(g)    grey_inverse[g]
  292.  
  293. static
  294. rgbi(r, g, b)
  295.     u_char r, g, b;
  296. {
  297.     return (r == g && g == b ? grey_inverse[r] :
  298.         red_inverse[r] + green_inverse[g] + blue_inverse[b]);
  299. }
  300.  
  301. #define    howmany(x, y)    (((x)+((y)-1))/(y))
  302. u_long    **BWmap;
  303. u_long    **PALmap;
  304.  
  305. static    gtTileContig();
  306. static    gtTileSeparate();
  307. static    gtStripContig();
  308. static    gtStripSeparate();
  309. static    void initYCbCrConversion();
  310.  
  311. static
  312. gt(tif, w, h, raster)
  313.     TIFF *tif;
  314.     int w, h;
  315.     u_long *raster;
  316. {
  317.     u_short minsamplevalue, maxsamplevalue, planarconfig;
  318.     RGBvalue *Map;
  319.     int e;
  320.  
  321.     TIFFGetFieldDefaulted(tif, TIFFTAG_MINSAMPLEVALUE, &minsamplevalue);
  322.     TIFFGetFieldDefaulted(tif, TIFFTAG_MAXSAMPLEVALUE, &maxsamplevalue);
  323.     Map = NULL;
  324.     switch (photometric) {
  325.     case PHOTOMETRIC_YCBCR:
  326.         TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRCOEFFICIENTS,
  327.             &YCbCrCoeffs);
  328.         TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING,
  329.             &YCbCrHorizSampling, &YCbCrVertSampling);
  330.         TIFFGetFieldDefaulted(tif, TIFFTAG_REFERENCEBLACKWHITE,
  331.             &refBlackWhite);
  332.         initYCbCrConversion();
  333.         /* fall thru... */
  334.     case PHOTOMETRIC_RGB:
  335.         if (minsamplevalue == 0 && maxsamplevalue == 255)
  336.             break;
  337.         /* fall thru... */
  338.     case PHOTOMETRIC_MINISBLACK:
  339.     case PHOTOMETRIC_MINISWHITE: {
  340.         register int x, range;
  341.  
  342.         range = maxsamplevalue - minsamplevalue;
  343.         Map = (RGBvalue *)malloc((range + 1) * sizeof (RGBvalue));
  344.         if (Map == NULL) {
  345.             TIFFError(filename,
  346.                 "No space for photometric conversion table");
  347.             return (0);
  348.         }
  349.         if (photometric == PHOTOMETRIC_MINISWHITE) {
  350.             for (x = 0; x <= range; x++)
  351.                 Map[x] = ((range - x) * 255) / range;
  352.         } else {
  353.             for (x = 0; x <= range; x++)
  354.                 Map[x] = (x * 255) / range;
  355.         }
  356.         if (bitspersample <= 8 &&
  357.             (photometric == PHOTOMETRIC_MINISBLACK ||
  358.              photometric == PHOTOMETRIC_MINISWHITE)) {
  359.             /*
  360.              * Use photometric mapping table to construct
  361.              * unpacking tables for samples <= 8 bits.
  362.              */
  363.             if (!makebwmap(Map))
  364.                 return (0);
  365.             /* no longer need Map, free it */
  366.             free((char *)Map);
  367.             Map = NULL;
  368.         }
  369.         break;
  370.     }
  371.     case PHOTOMETRIC_PALETTE:
  372.         if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
  373.             &redcmap, &greencmap, &bluecmap)) {
  374.             TIFFError(filename,
  375.                 "Missing required \"Colormap\" tag");
  376.             return (0);
  377.         }
  378.         /*
  379.          * Convert 16-bit colormap to 8-bit (unless it looks
  380.          * like an old-style 8-bit colormap).
  381.          */
  382.         if (checkcmap(1<<bitspersample, redcmap, greencmap, bluecmap) == 16) {
  383.             int i;
  384. #define    CVT(x)        (((x) * 255) / ((1L<<16)-1))
  385.             for (i = (1<<bitspersample)-1; i >= 0; i--) {
  386.                 redcmap[i] = CVT(redcmap[i]);
  387.                 greencmap[i] = CVT(greencmap[i]);
  388.                 bluecmap[i] = CVT(bluecmap[i]);
  389.             }
  390. #undef CVT
  391.         }
  392.         if (bitspersample <= 8) {
  393.             /*
  394.              * Use mapping table and colormap to construct
  395.              * unpacking tables for samples < 8 bits.
  396.              */
  397.             if (!makecmap(redcmap, greencmap, bluecmap))
  398.                 return (0);
  399.         }
  400.         break;
  401.     }
  402.     TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
  403.     if (planarconfig == PLANARCONFIG_SEPARATE && samplesperpixel > 1) {
  404.         e = TIFFIsTiled(tif) ?
  405.             gtTileSeparate(tif, raster, Map, h, w) :
  406.             gtStripSeparate(tif, raster, Map, h, w);
  407.     } else {
  408.         e = TIFFIsTiled(tif) ? 
  409.             gtTileContig(tif, raster, Map, h, w) :
  410.             gtStripContig(tif, raster, Map, h, w);
  411.     }
  412.     if (Map)
  413.         free((char *)Map);
  414.     return (e);
  415. }
  416.  
  417. u_long
  418. setorientation(tif, h)
  419.     TIFF *tif;
  420.     u_long h;
  421. {
  422.     u_long y;
  423.  
  424.     TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &orientation);
  425.     switch (orientation) {
  426.     case ORIENTATION_BOTRIGHT:
  427.     case ORIENTATION_RIGHTBOT:    /* XXX */
  428.     case ORIENTATION_LEFTBOT:    /* XXX */
  429.         TIFFWarning(filename, "using bottom-left orientation");
  430.         orientation = ORIENTATION_BOTLEFT;
  431.         /* fall thru... */
  432.     case ORIENTATION_BOTLEFT:
  433.         y = 0;
  434.         break;
  435.     case ORIENTATION_TOPRIGHT:
  436.     case ORIENTATION_RIGHTTOP:    /* XXX */
  437.     case ORIENTATION_LEFTTOP:    /* XXX */
  438.     default:
  439.         TIFFWarning(filename, "using top-left orientation");
  440.         orientation = ORIENTATION_TOPLEFT;
  441.         /* fall thru... */
  442.     case ORIENTATION_TOPLEFT:
  443.         y = h-1;
  444.         break;
  445.     }
  446.     return (y);
  447. }
  448.  
  449. typedef void (*tileContigRoutine)
  450.     (u_long*, u_char*, RGBvalue*, u_long, u_long, int, int);
  451. static tileContigRoutine pickTileContigCase(RGBvalue*);
  452.  
  453. /*
  454.  * Get an tile-organized image that has
  455.  *    PlanarConfiguration contiguous if SamplesPerPixel > 1
  456.  * or
  457.  *    SamplesPerPixel == 1
  458.  */    
  459. static
  460. gtTileContig(tif, raster, Map, h, w)
  461.     TIFF *tif;
  462.     u_long *raster;
  463.     RGBvalue *Map;
  464.     u_long h, w;
  465. {
  466.     u_long col, row, y;
  467.     u_long tw, th;
  468.     u_char *buf;
  469.     int fromskew, toskew;
  470.     u_int nrow;
  471.     tileContigRoutine put;
  472.  
  473.     buf = (u_char *)malloc(TIFFTileSize(tif));
  474.     if (buf == 0) {
  475.         TIFFError(filename, "No space for tile buffer");
  476.         return (0);
  477.     }
  478.     put = pickTileContigCase(Map);
  479.     TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
  480.     TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
  481.     y = setorientation(tif, h);
  482.     toskew = (orientation == ORIENTATION_TOPLEFT ? -tw + -w : -tw + w);
  483.     for (row = 0; row < h; row += th) {
  484.         nrow = (row + th > h ? h - row : th);
  485.         for (col = 0; col < w; col += tw) {
  486.             if (TIFFReadTile(tif, buf, col, row, 0, 0) < 0 && stoponerr)
  487.                 break;
  488.             if (col + tw > w) {
  489.                 /*
  490.                  * Tile is clipped horizontally.  Calculate
  491.                  * visible portion and skewing factors.
  492.                  */
  493.                 u_long npix = w - col;
  494.                 fromskew = tw - npix;
  495.                 (*put)(raster + y*w + col, buf, Map,
  496.                     npix, nrow, fromskew, toskew + fromskew);
  497.             } else
  498.                 (*put)(raster + y*w + col, buf, Map,
  499.                     tw, nrow, 0, toskew);
  500.         }
  501.         if (orientation == ORIENTATION_TOPLEFT) {
  502.             y -= nrow-1;
  503.             lrectwrite(0, y, w-1, y+nrow-1, raster + y*w);
  504.             y--;
  505.         } else {
  506.             lrectwrite(0, y, w-1, y+nrow-1, raster + y*w);
  507.             y += nrow;
  508.         }
  509.     }
  510.     free(buf);
  511.     return (1);
  512. }
  513.  
  514. typedef void (*tileSeparateRoutine)
  515.     (u_long*, u_char*, u_char*, u_char*, RGBvalue*, u_long, u_long, int, int);
  516. static tileSeparateRoutine pickTileSeparateCase(RGBvalue*);
  517.  
  518. /*
  519.  * Get an tile-organized image that has
  520.  *     SamplesPerPixel > 1
  521.  *     PlanarConfiguration separated
  522.  * We assume that all such images are RGB.
  523.  */    
  524. static
  525. gtTileSeparate(tif, raster, Map, h, w)
  526.     TIFF *tif;
  527.     u_long *raster;
  528.     RGBvalue *Map;
  529.     u_long h, w;
  530. {
  531.     u_long col, row, y;
  532.     u_long tw, th;
  533.     u_char *buf;
  534.     u_char *r, *g, *b;
  535.     int tilesize;
  536.     int fromskew, toskew;
  537.     u_int nrow;
  538.     tileSeparateRoutine put;
  539.  
  540.     tilesize = TIFFTileSize(tif);
  541.     buf = (u_char *)malloc(3*tilesize);
  542.     if (buf == 0) {
  543.         TIFFError(filename, "No space for tile buffer");
  544.         return (0);
  545.     }
  546.     r = buf;
  547.     g = r + tilesize;
  548.     b = g + tilesize;
  549.     put = pickTileSeparateCase(Map);
  550.     TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
  551.     TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
  552.     y = setorientation(tif, h);
  553.     toskew = (orientation == ORIENTATION_TOPLEFT ? -tw + -w : -tw + w);
  554.     for (row = 0; row < h; row += th) {
  555.         nrow = (row + th > h ? h - row : th);
  556.         for (col = 0; col < w; col += tw) {
  557.             if (TIFFReadTile(tif, r, col, row, 0, 0) < 0 && stoponerr)
  558.                 break;
  559.             if (TIFFReadTile(tif, g, col, row, 0, 1) < 0 && stoponerr)
  560.                 break;
  561.             if (TIFFReadTile(tif, b, col, row, 0, 2) < 0 && stoponerr)
  562.                 break;
  563.             if (col + tw > w) {
  564.                 /*
  565.                  * Tile is clipped horizontally.  Calculate
  566.                  * visible portion and skewing factors.
  567.                  */
  568.                 u_long npix = w - col;
  569.                 fromskew = tw - npix;
  570.                 (*put)(raster + y*w + col, r, g, b, Map,
  571.                     npix, nrow, fromskew, toskew + fromskew);
  572.             } else
  573.                 (*put)(raster + y*w + col, r, g, b, Map,
  574.                     tw, nrow, 0, toskew);
  575.         }
  576.         if (orientation == ORIENTATION_TOPLEFT) {
  577.             y -= nrow-1;
  578.             lrectwrite(0, y, w-1, y+nrow-1, raster + y*w);
  579.             y--;
  580.         } else {
  581.             lrectwrite(0, y, w-1, y+nrow-1, raster + y*w);
  582.             y += nrow;
  583.         }
  584.     }
  585.     free(buf);
  586.     return (1);
  587. }
  588.  
  589. /*
  590.  * Get a strip-organized image that has
  591.  *    PlanarConfiguration contiguous if SamplesPerPixel > 1
  592.  * or
  593.  *    SamplesPerPixel == 1
  594.  */    
  595. static
  596. gtStripContig(tif, raster, Map, h, w)
  597.     TIFF *tif;
  598.     u_long *raster;
  599.     RGBvalue *Map;
  600.     u_long h, w;
  601. {
  602.     u_long row, y, nrow;
  603.     u_char *buf;
  604.     tileContigRoutine put;
  605.     u_long rowsperstrip;
  606.     u_long imagewidth;
  607.     int scanline;
  608.     int fromskew, toskew;
  609.  
  610.     buf = (u_char *)malloc(TIFFStripSize(tif));
  611.     if (buf == 0) {
  612.         TIFFError(filename, "No space for strip buffer");
  613.         return (0);
  614.     }
  615.     put = pickTileContigCase(Map);
  616.     y = setorientation(tif, h);
  617.     toskew = (orientation == ORIENTATION_TOPLEFT ? -w + -w : -w + w);
  618.     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
  619.     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imagewidth);
  620.     scanline = TIFFScanlineSize(tif);
  621.     fromskew = (w < imagewidth ? imagewidth - w : 0);
  622.     for (row = 0; row < h; row += rowsperstrip) {
  623.         nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
  624.         if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
  625.             buf, nrow*scanline) < 0 && stoponerr)
  626.             break;
  627.         (*put)(raster + y*w, buf, Map, w, nrow, fromskew, toskew);
  628.         if (orientation == ORIENTATION_TOPLEFT) {
  629.             y -= nrow-1;
  630.             lrectwrite(0, y, w-1, y+nrow-1, raster + y*w);
  631.             y--;
  632.         } else {
  633.             lrectwrite(0, y, w-1, y+nrow-1, raster + y*w);
  634.             y += nrow;
  635.         }
  636.     }
  637.     free(buf);
  638.     return (1);
  639. }
  640.  
  641. /*
  642.  * Get a strip-organized image with
  643.  *     SamplesPerPixel > 1
  644.  *     PlanarConfiguration separated
  645.  * We assume that all such images are RGB.
  646.  */
  647. static
  648. gtStripSeparate(tif, raster, Map, h, w)
  649.     TIFF *tif;
  650.     u_long *raster;
  651.     register RGBvalue *Map;
  652.     u_long h, w;
  653. {
  654.     u_char *buf;
  655.     u_char *r, *g, *b;
  656.     u_long row, y, nrow;
  657.     int scanline;
  658.     tileSeparateRoutine put;
  659.     u_long rowsperstrip;
  660.     u_long imagewidth;
  661.     u_int stripsize;
  662.     int fromskew, toskew;
  663.  
  664.     stripsize = TIFFStripSize(tif);
  665.     r = buf = (u_char *)malloc(3*stripsize);
  666.     g = r + stripsize;
  667.     b = g + stripsize;
  668.     put = pickTileSeparateCase(Map);
  669.     y = setorientation(tif, h);
  670.     toskew = (orientation == ORIENTATION_TOPLEFT ? -w + -w : -w + w);
  671.     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
  672.     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imagewidth);
  673.     scanline = TIFFScanlineSize(tif);
  674.     fromskew = (w < imagewidth ? imagewidth - w : 0);
  675.     for (row = 0; row < h; row += rowsperstrip) {
  676.         nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
  677.         if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
  678.             r, nrow*scanline) < 0 && stoponerr)
  679.             break;
  680.         if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 1),
  681.             g, nrow*scanline) < 0 && stoponerr)
  682.             break;
  683.         if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 2),
  684.             b, nrow*scanline) < 0 && stoponerr)
  685.             break;
  686.         (*put)(raster + y*w, r, g, b, Map, w, nrow, fromskew, toskew);
  687.         if (orientation == ORIENTATION_TOPLEFT) {
  688.             y -= nrow-1;
  689.             lrectwrite(0, y, w-1, y+nrow-1, raster + y*w);
  690.             y--;
  691.         } else {
  692.             lrectwrite(0, y, w-1, y+nrow-1, raster + y*w);
  693.             y += nrow;
  694.         }
  695.     }
  696.     free(buf);
  697.     return (1);
  698. }
  699.  
  700. #define    PACK(r,g,b)    (r)|((g)<<8)|((b)<<16)
  701.  
  702. /*
  703.  * Greyscale images with less than 8 bits/sample are handled
  704.  * with a table to avoid lots of shifts and masks.  The table
  705.  * is setup so that put*bwtile (below) can retrieve 8/bitspersample
  706.  * pixel values simply by indexing into the table with one
  707.  * number.
  708.  */
  709. makebwmap(Map)
  710.     RGBvalue *Map;
  711. {
  712.     register int i;
  713.     int nsamples = 8 / bitspersample;
  714.     register u_long *p;
  715.  
  716.     BWmap = (u_long **)malloc(
  717.         256*sizeof (u_long *)+(256*nsamples*sizeof(u_long)));
  718.     if (BWmap == NULL) {
  719.         TIFFError(filename, "No space for B&W mapping table");
  720.         return (0);
  721.     }
  722.     p = (u_long *)(BWmap + 256);
  723.     if (isRGB) {
  724.         for (i = 0; i < 256; i++) {
  725.             BWmap[i] = p;
  726.             switch (bitspersample) {
  727.                 register RGBvalue c;
  728. #define    GREY(x)    c = Map[x]; *p++ = PACK(c,c,c);
  729.             case 1:
  730.                 GREY(i>>7);
  731.                 GREY((i>>6)&1);
  732.                 GREY((i>>5)&1);
  733.                 GREY((i>>4)&1);
  734.                 GREY((i>>3)&1);
  735.                 GREY((i>>2)&1);
  736.                 GREY((i>>1)&1);
  737.                 GREY(i&1);
  738.                 break;
  739.             case 2:
  740.                 GREY(i>>6);
  741.                 GREY((i>>4)&3);
  742.                 GREY((i>>2)&3);
  743.                 GREY(i&3);
  744.                 break;
  745.             case 4:
  746.                 GREY(i>>4);
  747.                 GREY(i&0xf);
  748.                 break;
  749.             case 8:
  750.                 GREY(i);
  751.                 break;
  752.             }
  753. #undef    GREY
  754.         }
  755.     } else {
  756.         for (i = 0; i < 256; i++) {
  757.             BWmap[i] = p;
  758.             switch (bitspersample) {
  759. #define    GREY(x)    *p++ = greyi(Map[x]);
  760.             case 1:
  761.                 GREY(i>>7);
  762.                 GREY((i>>6)&1);
  763.                 GREY((i>>5)&1);
  764.                 GREY((i>>4)&1);
  765.                 GREY((i>>3)&1);
  766.                 GREY((i>>2)&1);
  767.                 GREY((i>>1)&1);
  768.                 GREY(i&1);
  769.                 break;
  770.             case 2:
  771.                 GREY(i>>6);
  772.                 GREY((i>>4)&3);
  773.                 GREY((i>>2)&3);
  774.                 GREY(i&3);
  775.                 break;
  776.             case 4:
  777.                 GREY(i>>4);
  778.                 GREY(i&0xf);
  779.                 break;
  780.             case 8:
  781.                 GREY(i);
  782.                 break;
  783.             }
  784. #undef    GREY
  785.         }
  786.     }
  787.     return (1);
  788. }
  789.  
  790. /*
  791.  * Palette images with <= 8 bits/sample are handled
  792.  * with a table to avoid lots of shifts and masks.  The table
  793.  * is setup so that put*cmaptile (below) can retrieve 8/bitspersample
  794.  * pixel values simply by indexing into the table with one
  795.  * number.
  796.  */
  797. makecmap(rmap, gmap, bmap)
  798.     u_short *rmap, *gmap, *bmap;
  799. {
  800.     register int i;
  801.     int nsamples = 8 / bitspersample;
  802.     register u_long *p;
  803.  
  804.     PALmap = (u_long **)malloc(
  805.         256*sizeof (u_long *)+(256*nsamples*sizeof(u_long)));
  806.     if (PALmap == NULL) {
  807.         TIFFError(filename, "No space for Palette mapping table");
  808.         return (0);
  809.     }
  810.     p = (u_long *)(PALmap + 256);
  811.     if (isRGB) {
  812.         for (i = 0; i < 256; i++) {
  813.             PALmap[i] = p;
  814. #define    CMAP(x)    \
  815.     c = x; *p++ = PACK(rmap[c]&0xff, gmap[c]&0xff, bmap[c]&0xff);
  816.             switch (bitspersample) {
  817.                 register RGBvalue c;
  818.             case 1:
  819.                 CMAP(i>>7);
  820.                 CMAP((i>>6)&1);
  821.                 CMAP((i>>5)&1);
  822.                 CMAP((i>>4)&1);
  823.                 CMAP((i>>3)&1);
  824.                 CMAP((i>>2)&1);
  825.                 CMAP((i>>1)&1);
  826.                 CMAP(i&1);
  827.                 break;
  828.             case 2:
  829.                 CMAP(i>>6);
  830.                 CMAP((i>>4)&3);
  831.                 CMAP((i>>2)&3);
  832.                 CMAP(i&3);
  833.                 break;
  834.             case 4:
  835.                 CMAP(i>>4);
  836.                 CMAP(i&0xf);
  837.                 break;
  838.             case 8:
  839.                 CMAP(i);
  840.                 break;
  841.             }
  842. #undef CMAP
  843.         }
  844.     } else {
  845.         for (i = 0; i < 256; i++) {
  846.             PALmap[i] = p;
  847. #define    CMAP(x)    \
  848.     c = x; *p++ = rgbi(rmap[c], gmap[c], bmap[c]);
  849.             switch (bitspersample) {
  850.                 register RGBvalue c;
  851.             case 1:
  852.                 CMAP(i>>7);
  853.                 CMAP((i>>6)&1);
  854.                 CMAP((i>>5)&1);
  855.                 CMAP((i>>4)&1);
  856.                 CMAP((i>>3)&1);
  857.                 CMAP((i>>2)&1);
  858.                 CMAP((i>>1)&1);
  859.                 CMAP(i&1);
  860.                 break;
  861.             case 2:
  862.                 CMAP(i>>6);
  863.                 CMAP((i>>4)&3);
  864.                 CMAP((i>>2)&3);
  865.                 CMAP(i&3);
  866.                 break;
  867.             case 4:
  868.                 CMAP(i>>4);
  869.                 CMAP(i&0xf);
  870.                 break;
  871.             case 8:
  872.                 CMAP(i);
  873.                 break;
  874.             }
  875. #undef CMAP
  876.         }
  877.     }
  878.     return (1);
  879. }
  880.  
  881. /*
  882.  * The following routines move decoded data returned
  883.  * from the TIFF library into rasters that are suitable
  884.  * for passing to lrecwrite.  They do the necessary
  885.  * conversions based on whether the drawing mode is RGB
  886.  * colormap and whether or not there is a mapping table.
  887.  *
  888.  * The routines have been created according to the most
  889.  * important cases and optimized.  pickTileContigCase and
  890.  * pickTileSeparateCase analyze the parameters and select
  891.  * the appropriate "put" routine to use.
  892.  */
  893. #define    REPEAT8(op)    REPEAT4(op); REPEAT4(op)
  894. #define    REPEAT4(op)    REPEAT2(op); REPEAT2(op)
  895. #define    REPEAT2(op)    op; op
  896. #define    CASE8(x,op)                \
  897.     switch (x) {                \
  898.     case 7: op; case 6: op; case 5: op;    \
  899.     case 4: op; case 3: op; case 2: op;    \
  900.     case 1: op;                \
  901.     }
  902. #define    CASE4(x,op)    switch (x) { case 3: op; case 2: op; case 1: op; }
  903.  
  904. #define    UNROLL8(w, op1, op2) {        \
  905.     register u_long x;        \
  906.     for (x = w; x >= 8; x -= 8) {    \
  907.         op1;            \
  908.         REPEAT8(op2);        \
  909.     }                \
  910.     if (x > 0) {            \
  911.         op1;            \
  912.         CASE8(x,op2);        \
  913.     }                \
  914. }
  915. #define    UNROLL4(w, op1, op2) {        \
  916.     register u_long x;        \
  917.     for (x = w; x >= 4; x -= 4) {    \
  918.         op1;            \
  919.         REPEAT4(op2);        \
  920.     }                \
  921.     if (x > 0) {            \
  922.         op1;            \
  923.         CASE4(x,op2);        \
  924.     }                \
  925. }
  926. #define    UNROLL2(w, op1, op2) {        \
  927.     register u_long x;        \
  928.     for (x = w; x >= 2; x -= 2) {    \
  929.         op1;            \
  930.         REPEAT2(op2);        \
  931.     }                \
  932.     if (x) {            \
  933.         op1;            \
  934.         op2;            \
  935.     }                \
  936. }
  937.             
  938.  
  939. #define    SKEW(r,g,b,skew)    { r += skew; g += skew; b += skew; }
  940.  
  941. /*
  942.  * 8-bit packed samples => colormap
  943.  */
  944. static void
  945. putcontig8bittile(cp, pp, Map, w, h, fromskew, toskew)
  946.     register u_long *cp;
  947.     register u_char *pp;
  948.     register RGBvalue *Map;
  949.     u_long w, h;
  950.     int fromskew, toskew;
  951. {
  952.     register u_long x;
  953.  
  954.     fromskew *= samplesperpixel;
  955.     if (Map) {
  956.         while (h-- > 0) {
  957.             for (x = w; x-- > 0;) {
  958.                 *cp++ = rgbi(Map[pp[0]], Map[pp[1]], Map[pp[2]]);
  959.                 pp += samplesperpixel;
  960.             }
  961.             cp += toskew;
  962.             pp += fromskew;
  963.         }
  964.     } else {
  965.         while (h-- > 0) {
  966.             for (x = w; x-- > 0;) {
  967.                 *cp++ = rgbi(pp[0], pp[1], pp[2]);
  968.                 pp += samplesperpixel;
  969.             }
  970.             cp += toskew;
  971.             pp += fromskew;
  972.         }
  973.     }
  974. }
  975.  
  976. /*
  977.  * 16-bit packed samples => colormap
  978.  */
  979. static void
  980. putcontig16bittile(cp, pp, Map, w, h, fromskew, toskew)
  981.     register u_long *cp;
  982.     register u_short *pp;
  983.     register RGBvalue *Map;
  984.     u_long w, h;
  985.     int fromskew, toskew;
  986. {
  987.     register u_long x;
  988.  
  989.     fromskew *= samplesperpixel;
  990.     if (Map) {
  991.         while (h-- > 0) {
  992.             for (x = w; x-- > 0;) {
  993.                 *cp++ = rgbi(Map[pp[0]], Map[pp[1]], Map[pp[2]]);
  994.                 pp += samplesperpixel;
  995.             }
  996.             cp += toskew;
  997.             pp += fromskew;
  998.         }
  999.     } else {
  1000.         while (h-- > 0) {
  1001.             for (x = w; x-- > 0;) {
  1002.                 *cp++ = rgbi(pp[0], pp[1], pp[2]);
  1003.                 pp += samplesperpixel;
  1004.             }
  1005.             cp += toskew;
  1006.             pp += fromskew;
  1007.         }
  1008.     }
  1009. }
  1010.  
  1011. /*
  1012.  * 8-bit unpacked samples => colormap
  1013.  */
  1014. static void
  1015. putseparate8bittile(cp, r, g, b, Map, w, h, fromskew, toskew)
  1016.     register u_long *cp;
  1017.     register u_char *r, *g, *b;
  1018.     register RGBvalue *Map;
  1019.     u_long w, h;
  1020.     int fromskew, toskew;
  1021.  
  1022. {
  1023.     register u_long x;
  1024.  
  1025.     if (Map) {
  1026.         while (h-- > 0) {
  1027.             for (x = w; x-- > 0;)
  1028.                 *cp++ =
  1029.                   rgbi(Map[*r++], Map[*g++], Map[*b++]);
  1030.             SKEW(r, g, b, fromskew);
  1031.             cp += toskew;
  1032.         }
  1033.     } else {
  1034.         while (h-- > 0) {
  1035.             for (x = w; x-- > 0;)
  1036.                 *cp++ = rgbi(*r++, *g++, *b++);
  1037.             SKEW(r, g, b, fromskew);
  1038.             cp += toskew;
  1039.         }
  1040.     }
  1041. }
  1042.  
  1043. /*
  1044.  * 16-bit unpacked samples => colormap
  1045.  */
  1046. static void
  1047. putseparate16bittile(cp, r, g, b, Map, w, h, fromskew, toskew)
  1048.     register u_long *cp;
  1049.     register u_short *r, *g, *b;
  1050.     register RGBvalue *Map;
  1051.     u_long w, h;
  1052.     int fromskew, toskew;
  1053. {
  1054.     register u_long x;
  1055.  
  1056.     if (Map) {
  1057.         while (h-- > 0) {
  1058.             for (x = 0; x < w; x++)
  1059.                 *cp++ =
  1060.                   rgbi(Map[*r++], Map[*g++], Map[*b++]);
  1061.             SKEW(r, g, b, fromskew);
  1062.             cp += toskew;
  1063.         }
  1064.     } else {
  1065.         while (h-- > 0) {
  1066.             for (x = 0; x < w; x++)
  1067.                 *cp++ = rgbi(*r++, *g++, *b++);
  1068.             SKEW(r, g, b, fromskew);
  1069.             cp += toskew;
  1070.         }
  1071.     }
  1072. }
  1073.  
  1074. /*
  1075.  * 8-bit palette => colormap/RGB
  1076.  */
  1077. static void
  1078. put8bitcmaptile(cp, pp, Map, w, h, fromskew, toskew)
  1079.     register u_long *cp;
  1080.     register u_char *pp;
  1081.     RGBvalue *Map;
  1082.     u_long w, h;
  1083.     int fromskew, toskew;
  1084. {
  1085.     while (h-- > 0) {
  1086.         UNROLL8(w,, *cp++ = PALmap[*pp++][0]);
  1087.         cp += toskew;
  1088.         pp += fromskew;
  1089.     }
  1090. }
  1091.  
  1092. /*
  1093.  * 4-bit palette => colormap/RGB
  1094.  */
  1095. static void
  1096. put4bitcmaptile(cp, pp, Map, w, h, fromskew, toskew)
  1097.     register u_long *cp;
  1098.     register u_char *pp;
  1099.     register RGBvalue *Map;
  1100.     u_long w, h;
  1101.     int fromskew, toskew;
  1102. {
  1103.     register u_long *bw;
  1104.  
  1105.     fromskew /= 2;
  1106.     while (h-- > 0) {
  1107.         UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++);
  1108.         cp += toskew;
  1109.         pp += fromskew;
  1110.     }
  1111. }
  1112.  
  1113. /*
  1114.  * 2-bit palette => colormap/RGB
  1115.  */
  1116. static void
  1117. put2bitcmaptile(cp, pp, Map, w, h, fromskew, toskew)
  1118.     register u_long *cp;
  1119.     register u_char *pp;
  1120.     register RGBvalue *Map;
  1121.     u_long w, h;
  1122.     int fromskew, toskew;
  1123. {
  1124.     register u_long *bw;
  1125.  
  1126.     fromskew /= 4;
  1127.     while (h-- > 0) {
  1128.         UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++);
  1129.         cp += toskew;
  1130.         pp += fromskew;
  1131.     }
  1132. }
  1133.  
  1134. /*
  1135.  * 1-bit palette => colormap/RGB
  1136.  */
  1137. static void
  1138. put1bitcmaptile(cp, pp, Map, w, h, fromskew, toskew)
  1139.     register u_long *cp;
  1140.     register u_char *pp;
  1141.     register RGBvalue *Map;
  1142.     u_long w, h;
  1143.     int fromskew, toskew;
  1144. {
  1145.     register u_long *bw;
  1146.  
  1147.     fromskew /= 8;
  1148.     while (h-- > 0) {
  1149.         UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++);
  1150.         cp += toskew;
  1151.         pp += fromskew;
  1152.     }
  1153. }
  1154.  
  1155. /*
  1156.  * 8-bit greyscale => colormap/RGB
  1157.  */
  1158. static void
  1159. putgreytile(cp, pp, Map, w, h, fromskew, toskew)
  1160.     register u_long *cp;
  1161.     register u_char *pp;
  1162.     RGBvalue *Map;
  1163.     u_long w, h;
  1164.     int fromskew, toskew;
  1165. {
  1166.     while (h-- > 0) {
  1167.         register u_long x;
  1168.         for (x = w; x-- > 0;)
  1169.             *cp++ = BWmap[*pp++][0];
  1170.         cp += toskew;
  1171.         pp += fromskew;
  1172.     }
  1173. }
  1174.  
  1175. /*
  1176.  * 1-bit bilevel => colormap/RGB
  1177.  */
  1178. static void
  1179. put1bitbwtile(cp, pp, Map, w, h, fromskew, toskew)
  1180.     u_long *cp;
  1181.     u_char *pp;
  1182.     RGBvalue **Map;
  1183.     u_long w, h;
  1184.     int fromskew, toskew;
  1185. {
  1186.     register u_long *bw;
  1187.  
  1188.     fromskew /= 8;
  1189.     while (h-- > 0) {
  1190.         UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
  1191.         cp += toskew;
  1192.         pp += fromskew;
  1193.     }
  1194. }
  1195.  
  1196. /*
  1197.  * 2-bit greyscale => colormap/RGB
  1198.  */
  1199. static void
  1200. put2bitbwtile(cp, pp, Map, w, h, fromskew, toskew)
  1201.     u_long *cp;
  1202.     u_char *pp;
  1203.     RGBvalue **Map;
  1204.     u_long w, h;
  1205.     int fromskew, toskew;
  1206. {
  1207.     register u_long *bw;
  1208.  
  1209.     fromskew /= 4;
  1210.     while (h-- > 0) {
  1211.         UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++);
  1212.         cp += toskew;
  1213.         pp += fromskew;
  1214.     }
  1215. }
  1216.  
  1217. /*
  1218.  * 4-bit greyscale => colormap/RGB
  1219.  */
  1220. static void
  1221. put4bitbwtile(cp, pp, Map, w, h, fromskew, toskew)
  1222.     u_long *cp;
  1223.     u_char *pp;
  1224.     RGBvalue **Map;
  1225.     u_long w, h;
  1226.     int fromskew, toskew;
  1227. {
  1228.     register u_long *bw;
  1229.  
  1230.     fromskew /= 2;
  1231.     while (h-- > 0) {
  1232.         UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++);
  1233.         cp += toskew;
  1234.         pp += fromskew;
  1235.     }
  1236. }
  1237.  
  1238. /*
  1239.  * 8-bit packed RGB samples => RGB
  1240.  */
  1241. static void
  1242. putRGBcontig8bittile(cp, pp, Map, w, h, fromskew, toskew)
  1243.     register u_long *cp;
  1244.     register u_char *pp;
  1245.     register RGBvalue *Map;
  1246.     u_long w, h;
  1247.     int fromskew, toskew;
  1248. {
  1249.     fromskew *= samplesperpixel;
  1250.     if (Map) {
  1251.         while (h-- > 0) {
  1252.             register u_long x;
  1253.             for (x = w; x-- > 0;) {
  1254.                 *cp++ = PACK(Map[pp[0]], Map[pp[1]], Map[pp[2]]);
  1255.                 pp += samplesperpixel;
  1256.             }
  1257.             pp += fromskew;
  1258.             cp += toskew;
  1259.         }
  1260.     } else {
  1261.         while (h-- > 0) {
  1262.             UNROLL8(w,,
  1263.                 *cp++ = PACK(pp[0], pp[1], pp[2]);
  1264.                 pp += samplesperpixel);
  1265.             cp += toskew;
  1266.             pp += fromskew;
  1267.         }
  1268.     }
  1269. }
  1270.  
  1271. /*
  1272.  * 16-bit packed RGB samples => RGB
  1273.  */
  1274. static void
  1275. putRGBcontig16bittile(cp, pp, Map, w, h, fromskew, toskew)
  1276.     register u_long *cp;
  1277.     register u_short *pp;
  1278.     register RGBvalue *Map;
  1279.     u_long w, h;
  1280.     int fromskew, toskew;
  1281. {
  1282.     register u_int x;
  1283.  
  1284.     fromskew *= samplesperpixel;
  1285.     if (Map) {
  1286.         while (h-- > 0) {
  1287.             for (x = w; x-- > 0;) {
  1288.                 *cp++ = PACK(Map[pp[0]], Map[pp[1]], Map[pp[2]]);
  1289.                 pp += samplesperpixel;
  1290.             }
  1291.             cp += toskew;
  1292.             pp += fromskew;
  1293.         }
  1294.     } else {
  1295.         while (h-- > 0) {
  1296.             for (x = w; x-- > 0;) {
  1297.                 *cp++ = PACK(pp[0], pp[1], pp[2]);
  1298.                 pp += samplesperpixel;
  1299.             }
  1300.             cp += toskew;
  1301.             pp += fromskew;
  1302.         }
  1303.     }
  1304. }
  1305.  
  1306. /*
  1307.  * 8-bit unpacked RGB samples => RGB
  1308.  */
  1309. static void
  1310. putRGBseparate8bittile(cp, r, g, b, Map, w, h, fromskew, toskew)
  1311.     register u_long *cp;
  1312.     register u_char *r, *g, *b;
  1313.     register RGBvalue *Map;
  1314.     u_long w, h;
  1315.     int fromskew, toskew;
  1316.  
  1317. {
  1318.     if (Map) {
  1319.         while (h-- > 0) {
  1320.             register u_long x;
  1321.             for (x = w; x > 0; x--)
  1322.                 *cp++ = PACK(Map[*r++], Map[*g++], Map[*b++]);
  1323.             SKEW(r, g, b, fromskew);
  1324.             cp += toskew;
  1325.         }
  1326.     } else {
  1327.         while (h-- > 0) {
  1328.             UNROLL8(w,, *cp++ = PACK(*r++, *g++, *b++));
  1329.             SKEW(r, g, b, fromskew);
  1330.             cp += toskew;
  1331.         }
  1332.     }
  1333. }
  1334.  
  1335. /*
  1336.  * 16-bit unpacked RGB samples => RGB
  1337.  */
  1338. static void
  1339. putRGBseparate16bittile(cp, r, g, b, Map, w, h, fromskew, toskew)
  1340.     register u_long *cp;
  1341.     register u_short *r, *g, *b;
  1342.     register RGBvalue *Map;
  1343.     u_long w, h;
  1344.     int fromskew, toskew;
  1345. {
  1346.     register u_long x;
  1347.  
  1348.     if (Map) {
  1349.         while (h-- > 0) {
  1350.             for (x = w; x > 0; x--)
  1351.                 *cp++ = PACK(Map[*r++], Map[*g++], Map[*b++]);
  1352.             SKEW(r, g, b, fromskew);
  1353.             cp += toskew;
  1354.         }
  1355.     } else {
  1356.         while (h-- > 0) {
  1357.             for (x = 0; x < w; x++)
  1358.                 *cp++ = PACK(*r++, *g++, *b++);
  1359.             SKEW(r, g, b, fromskew);
  1360.             cp += toskew;
  1361.         }
  1362.     }
  1363. }
  1364.  
  1365. #define    Code2V(c, RB, RW, CR)    ((((c)-RB)*(float)CR)/(float)(RW-RB))
  1366. #define    CLAMP(f,min,max) \
  1367.     (int)((f)+.5 < (min) ? (min) : (f)+.5 > (max) ? (max) : (f)+.5)
  1368.  
  1369. #define    LumaRed        YCbCrCoeffs[0]
  1370. #define    LumaGreen    YCbCrCoeffs[1]
  1371. #define    LumaBlue    YCbCrCoeffs[2]
  1372.  
  1373. static    float D1, D2;
  1374. static    float D3, D4;
  1375.  
  1376. static void
  1377. initYCbCrConversion()
  1378. {
  1379.     D1 = 2 - 2*LumaRed;
  1380.     D2 = D1*LumaRed / LumaGreen;
  1381.     D3 = 2 - 2*LumaBlue;
  1382.     D4 = D2*LumaBlue / LumaGreen;
  1383. }
  1384.  
  1385. static void
  1386. putRGBContigYCbCrClump(cp, pp, cw, ch, w, n, fromskew, toskew)
  1387.     register u_long *cp;
  1388.     register u_char *pp;
  1389.     int cw, ch;
  1390.     u_long w;
  1391.     int n, fromskew, toskew;
  1392. {
  1393.     float Cb, Cr;
  1394.     int j, k;
  1395.  
  1396.     Cb = Code2V(pp[n],   refBlackWhite[2], refBlackWhite[3], 127);
  1397.     Cr = Code2V(pp[n+1], refBlackWhite[4], refBlackWhite[5], 127);
  1398.     for (j = 0; j < ch; j++) {
  1399.         for (k = 0; k < cw; k++) {
  1400.             float Y, R, G, B;
  1401.             Y = Code2V(*pp++,
  1402.                 refBlackWhite[0], refBlackWhite[1], 255);
  1403.             R = Y + Cr*D1;
  1404.             B = Y + Cb*D3;
  1405.             G = Y - Cb*D4 - Cr*D2;
  1406.             cp[k] = PACK(CLAMP(R,0,255),
  1407.                      CLAMP(G,0,255),
  1408.                      CLAMP(B,0,255));
  1409.         }
  1410.         cp += w+toskew;
  1411.         pp += fromskew;
  1412.     }
  1413. }
  1414.  
  1415. static void
  1416. putCmapContigYCbCrClump(cp, pp, cw, ch, w, n, fromskew, toskew)
  1417.     register u_long *cp;
  1418.     register u_char *pp;
  1419.     int cw, ch;
  1420.     u_long w;
  1421.     int n, fromskew, toskew;
  1422. {
  1423.     float Cb, Cr;
  1424.     int j, k;
  1425.  
  1426.     Cb = Code2V(pp[n],   refBlackWhite[2], refBlackWhite[3], 127);
  1427.     Cr = Code2V(pp[n+1], refBlackWhite[4], refBlackWhite[5], 127);
  1428.     for (j = 0; j < ch; j++) {
  1429.         for (k = 0; k < cw; k++) {
  1430.             float Y, R, G, B;
  1431.             Y = Code2V(*pp++,
  1432.                 refBlackWhite[0], refBlackWhite[1], 255);
  1433.             R = Y + Cr*D1;
  1434.             B = Y + Cb*D3;
  1435.             G = Y - Cb*D4 - Cr*D2;
  1436.             cp[k] = rgbi(CLAMP(R,0,255),
  1437.                      CLAMP(G,0,255),
  1438.                      CLAMP(B,0,255));
  1439.         }
  1440.         cp += w+toskew;
  1441.         pp += fromskew;
  1442.     }
  1443. }
  1444. #undef LumaBlue
  1445. #undef LumaGreen
  1446. #undef LumaRed
  1447. #undef CLAMP
  1448. #undef Code2V
  1449.  
  1450. typedef void (*YCbCrPut)(u_long*, u_char*, int, int, u_long, int, int, int);
  1451.  
  1452. /*
  1453.  * 8-bit packed YCbCr samples => RGB
  1454.  */
  1455. static void
  1456. putcontig8bitYCbCrtile(cp, pp, Map, w, h, fromskew, toskew)
  1457.     register u_long *cp;
  1458.     register u_char *pp;
  1459.     register RGBvalue *Map;
  1460.     u_long w, h;
  1461.     int fromskew, toskew;
  1462. {
  1463.     YCbCrPut put;
  1464.     u_int Coff = YCbCrVertSampling * YCbCrHorizSampling;
  1465.     u_long *tp;
  1466.     u_long x;
  1467.  
  1468.     /* XXX adjust fromskew */
  1469.     put = (isRGB ? putRGBContigYCbCrClump : putCmapContigYCbCrClump);
  1470.     while (h >= YCbCrVertSampling) {
  1471.         tp = cp;
  1472.         for (x = w; x >= YCbCrHorizSampling; x -= YCbCrHorizSampling) {
  1473.             (*put)(tp, pp, YCbCrHorizSampling, YCbCrVertSampling,
  1474.                 w, Coff, 0, toskew);
  1475.             tp += YCbCrHorizSampling;
  1476.             pp += Coff+2;
  1477.         }
  1478.         if (x > 0) {
  1479.             (*put)(tp, pp, x, YCbCrVertSampling,
  1480.                 w, Coff, YCbCrHorizSampling - x, toskew);
  1481.             pp += Coff+2;
  1482.         }
  1483.         cp += YCbCrVertSampling*(w + toskew);
  1484.         pp += fromskew;
  1485.         h -= YCbCrVertSampling;
  1486.     }
  1487.     if (h > 0) {
  1488.         tp = cp;
  1489.         for (x = w; x >= YCbCrHorizSampling; x -= YCbCrHorizSampling) {
  1490.             (*put)(tp, pp, YCbCrHorizSampling, h,
  1491.                 w, Coff, 0, toskew);
  1492.             tp += YCbCrHorizSampling;
  1493.             pp += Coff+2;
  1494.         }
  1495.         if (x > 0)
  1496.             (*put)(tp, pp, x, h,
  1497.                 w, Coff, YCbCrHorizSampling - x, toskew);
  1498.     }
  1499. }
  1500.  
  1501. /*
  1502.  * Select the appropriate conversion routine for packed data.
  1503.  */
  1504. static tileContigRoutine
  1505. pickTileContigCase(RGBvalue* Map)
  1506. {
  1507.     tileContigRoutine put = 0;
  1508.  
  1509.     switch (photometric) {
  1510.     case PHOTOMETRIC_RGB:
  1511.         if (isRGB) {
  1512.             put = (bitspersample == 8 ?
  1513.                 putRGBcontig8bittile : putRGBcontig16bittile);
  1514.         } else {
  1515.             put = (bitspersample == 8 ?
  1516.                 putcontig8bittile : putcontig16bittile);
  1517.         }
  1518.         break;
  1519.     case PHOTOMETRIC_PALETTE:
  1520.         switch (bitspersample) {
  1521.         case 8:    put = put8bitcmaptile; break;
  1522.         case 4: put = put4bitcmaptile; break;
  1523.         case 2: put = put2bitcmaptile; break;
  1524.         case 1: put = put1bitcmaptile; break;
  1525.         }
  1526.         break;
  1527.     case PHOTOMETRIC_MINISWHITE:
  1528.     case PHOTOMETRIC_MINISBLACK:
  1529.         switch (bitspersample) {
  1530.         case 8:    put = putgreytile; break;
  1531.         case 4: put = put4bitbwtile; break;
  1532.         case 2: put = put2bitbwtile; break;
  1533.         case 1: put = put1bitbwtile; break;
  1534.         }
  1535.         break;
  1536.     case PHOTOMETRIC_YCBCR:
  1537.         switch (bitspersample) {
  1538.         case 8: put = putcontig8bitYCbCrtile; break;
  1539.         }
  1540.         break;
  1541.     }
  1542.     if (pick == 0) {
  1543.         TIFFError(filename, "Can not handle file");
  1544.         exit(-1);
  1545.     }
  1546.     return (put);
  1547. }
  1548.  
  1549. /*
  1550.  * Select the appropriate conversion routine for unpacked data.
  1551.  *
  1552.  * NB: we assume that unpacked single channel data is directed
  1553.  *     to the "packed routines.
  1554.  */
  1555. static tileSeparateRoutine
  1556. pickTileSeparateCase(RGBvalue* Map)
  1557. {
  1558.     tileSeparateRoutine put = 0;
  1559.  
  1560.     switch (photometric) {
  1561.     case PHOTOMETRIC_RGB:
  1562.         if (isRGB) {
  1563.             put = (bitspersample == 8 ?
  1564.                 putRGBseparate8bittile : putRGBseparate16bittile);
  1565.         } else {
  1566.             put = (bitspersample == 8 ?
  1567.                 putseparate8bittile : putseparate16bittile);
  1568.         }
  1569.         break;
  1570.     }
  1571.     if (pick == 0) {
  1572.         TIFFError(filename, "Can not handle file");
  1573.         exit(-1);
  1574.     }
  1575.     return (put);
  1576. }
  1577.